<?php

/**
 * SummerNote field, using jQuery
 * @package forms
 */
class SummerNoteField extends TextareaField {
    private static $allowed_actions = array(
        'upload_image'
    );
    
    /**
     * @config
     * @var Integer Default insertion width for Images and Media
     */
    private static $insert_width = 600;

    protected $rows = 30;
    
    /**
     * Partial filesystem path relative to /assets directory.
     * Defaults to Upload::$uploads_folder.
     *
     * @var string
     */
    protected $folderName = false;
    
    /**
     * @see TextareaField::__construct()
     */
    public function __construct($name, $title = null, $value = '') {
        parent::__construct($name, $title, $value);
            
        Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
        Requirements::css('general/thirdparty/bootstrap/css/bootstrap.min.css');
        Requirements::javascript('general/thirdparty/bootstrap/js/bootstrap.min.js');
        Requirements::css('general/thirdparty/font-awesome/css/font-awesome.min.css');
        Requirements::css('general/thirdparty/summernote/dist/summernote.css');
        Requirements::javascript('general/thirdparty/summernote/dist/summernote.min.js');
        Requirements::javascript('general/javascript/SummerNoteField.min.js');
    }
    
    function getAttributes() {
        $attributes = parent::getAttributes();
        if(isset($attributes['required'])) unset($attributes['required']);
        if(isset($attributes['aria-required'])) unset($attributes['aria-required']);
        return array_merge(
            $attributes, 
            array(
            	'rel' => 'summernote',
                'data-upload-image' => $this->Link('upload_image')
            )
        );
    }
    
    /**
     * @return string
     */
    public function Field($properties = array()) {
        // mark up broken links
        $value = Injector::inst()->create('HTMLValue', $this->value);

        if($links = $value->getElementsByTagName('a')) foreach($links as $link) {
            $matches = array();
            
            if(preg_match('/\[sitetree_link(?:\s*|%20|,)?id=([0-9]+)\]/i', $link->getAttribute('href'), $matches)) {
                if(!DataObject::get_by_id('SiteTree', $matches[1])) {
                    $class = $link->getAttribute('class');
                    $link->setAttribute('class', ($class ? "$class ss-broken" : 'ss-broken'));
                }
            }

            if(preg_match('/\[file_link(?:\s*|%20|,)?id=([0-9]+)\]/i', $link->getAttribute('href'), $matches)) {
                if(!DataObject::get_by_id('File', $matches[1])) {
                    $class = $link->getAttribute('class');
                    $link->setAttribute('class', ($class ? "$class ss-broken" : 'ss-broken'));
                }
            }
        }

        $properties['Value'] = htmlentities($value->getContent(), ENT_COMPAT, 'UTF-8');
        $obj = $this->customise($properties);

        return $obj->renderWith($this->getTemplates());
    }

    public function saveInto(DataObjectInterface $record) {
        if($record->hasField($this->name) && $record->escapeTypeForField($this->name) != 'xml') {
            throw new Exception (
                'SummerNoteField->saveInto(): This field should save into a HTMLText or HTMLVarchar field.'
            );
        }
        
        $htmlValue = Injector::inst()->create('HTMLValue', $this->value);

        // Sanitise if requested
        if(Config::inst()->get('HtmlEditorField', 'sanitise_server_side')) {
            $santiser = Injector::inst()->create('HtmlEditorSanitiser', HtmlEditorConfig::get_active());
            $santiser->sanitise($htmlValue);
        }

        // Resample images and add default attributes
        if($images = $htmlValue->getElementsByTagName('img')) foreach($images as $img) {
            // strip any ?r=n data from the src attribute
            $img->setAttribute('src', preg_replace('/([^\?]*)\?r=[0-9]+$/i', '$1', $img->getAttribute('src')));

            // Resample the images if the width & height have changed.
            if($image = File::find(urldecode(Director::makeRelative($img->getAttribute('src'))))){
                $width  = $img->getAttribute('width');
                $height = $img->getAttribute('height');

                if($width && $height && ($width != $image->getWidth() || $height != $image->getHeight())) {
                    //Make sure that the resized image actually returns an image:
                    $resized=$image->ResizedImage($width, $height);
                    if($resized) $img->setAttribute('src', $resized->getRelativePath());
                }
            }

            // Add default empty title & alt attributes.
            if(!$img->getAttribute('alt')) $img->setAttribute('alt', '');
            if(!$img->getAttribute('title')) $img->setAttribute('title', '');
        }

        // Store into record
        $record->{$this->name} = $htmlValue->getContent();
    }

    /**
     * Sets the upload folder name
     * 
     * @param string $folderName
     * @return FileField Self reference
     */
    public function setFolderName($folderName) {
        $this->folderName = $folderName;
        return $this;
    }
    
    /**
     * Gets the upload folder name
     * 
     * @return string
     */
    public function getFolderName() {
        return ($this->folderName !== false) ? $this->folderName : Config::inst()->get('Upload', 'uploads_folder');
    }

    /**
     * Handle a request for upload image.
     * 
     * @param HTTPRequest $request The request to handle.
     * @return A list of items for Autocomplete.
     */
    function upload_image(HTTPRequest $request) {
        $tmpfile = $request->postVar('file');
        
        // Check if the file has been uploaded into the temporary storage.
        if (!$tmpfile) {
            $return = array('error' => _t('SummerNoteField.FILE_NOT_FOUND', 'File information not found'));
        } else {
            $return = array(
                'name' => $tmpfile['name'],
                'size' => $tmpfile['size'],
                'type' => $tmpfile['type'],
                'error' => $tmpfile['error'],
                'tmp_name' => $tmpfile['tmp_name']
            );
        }
        
        $upload = Upload::create();
        
        $upload->getValidator()->setAllowedExtensions(array(
            'jpg',
            'jpeg',
            'png',
            'gif'
        )); 
        
        // get the lower max size
        $upload->getValidator()->setAllowedMaxFileSize(min(File::ini2bytes(ini_get('upload_max_filesize')), File::ini2bytes(ini_get('post_max_size'))));
        
        // Process the uploaded file
        if (!$return['error']) {
            try {
                $upload->load($return, $this->folderName);
            } catch (Exception $e) {
                // we shouldn't get an error here, but just in case
                $return['error'] = $e->getMessage();
            }

            if (!$return['error']) {
                if ($upload->isError()) {
                    $return['error'] = implode(' '.PHP_EOL, $upload->getErrors());
                } else {
                    $file = $upload->getFile();
                    // Collect all output data.
                    $return['path'] = $file->getRelativePath();
                }
            }
        }
        $response = new SS_HTTPResponse(Convert::array2json($return));
        $response->addHeader('Content-Type', 'application/json');
        return $response;
    }
}
?>
